<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Slot Drag Event</title>
    <style>
        div.drop-slot {
            border: 2px solid #333;
            border-radius: 4px;
            height: 6em;
            display: flex;
        }
    </style>
</head>

<body>
    <main>

    </main>
    <div>
        <tp-drop title="slot-1" id="slot-1">
            <div class="drop-slot" slot="ctn" ondrop="drop_handler(event);" ondragover="dragover_handler(event);">AAA
            </div>
        </tp-drop>
        <tp-drop title="slot-2" id="slot-2">
            <div class="drop-slot" slot="ctn" ondrop="drop_handler(event);" ondragover="dragover_handler(event);">BBB
            </div>
        </tp-drop>
        <tp-drop title="slot-3" id="slot-3">
            <div class="drop-slot" slot="ctn" ondrop="drop_handler(event);" ondragover="dragover_handler(event);">CCC
            </div>
        </tp-drop>

        <tp-drag title="d1" id="d1"></tp-drag>
        <tp-drag title="d2" id="d2"></tp-drag>
        <tp-drag title="d3" id="d3"></tp-drag>
        <tp-drag title="d4" id="d4"></tp-drag>

    </div>

    <!--  ================= drag script ====================== -->
    <script>
        dragstart_handler = (ev) => {
            console.log("dragStart");

            ev.currentTarget.style.border = "dashed";

            ev.dataTransfer.setData("text", ev.target.getAttribute('cid'));

            ev.effectAllowed = "copyMove";
        }
        dragover_handler = (ev) => {
            console.log("dragOver");
            // Change the target element's border to signify a drag over event
            // has occurred
            ev.currentTarget.style.background = "lightblue";
            ev.preventDefault();
        }
        drop_handler = (ev) => {
            console.log("Drop");
            ev.preventDefault();
            let id = ev.dataTransfer.getData("text");
            
            // !!!!  Don't Use ev.target
            // it will appendChild in wrong position
            // ev.target.appendChild(document.getElementById(id));

            ev.currentTarget.appendChild(document.getElementById(id));
        }
        dragend_handler = (ev) => {
            console.log("dragEnd");
            // Restore source's border
            ev.target.style.border = "solid black";
            // Remove all of the drag data
            ev.dataTransfer.clearData();
        }
    </script>


    <!--  ================= tp-drop =========================== -->
    <template id="tp-drop">
        <style>
            p#title {
                color: red;
            }
        </style>
        <div>
            <p id="title"></p>
            <slot name="ctn"></slot>
        </div>
    </template>


    <script>
        class TpDrop extends HTMLElement {
            constructor() {
                super();


                let template = document.getElementById('tp-drop');

                let shadow = this.attachShadow({ mode: 'closed' });

                let tp_content = template.content.cloneNode(true);

                this.$title = tp_content.getElementById('title');

                this.$title.textContent = this.getAttribute('title');

                shadow.appendChild(tp_content);
            }

        }

        customElements.define('tp-drop', TpDrop);

    </script>

    <!--  ================= tp-drag =========================== -->
    <template id="tp-drag">
        <style>
            div#content {
                color: #fff;
                width: 2em;
                height: 2em;
                margin: 1em;
                text-align: center;
                font-size: 1em;
                border-radius: 50%;
                line-height: 2em;
                background-color: #9ae;

            }
        </style>
        <div id="content" draggable="true" ondragstart="dragstart_handler(event);" ondragend="dragend_handler(event);">
            <span id="title"></span>
        </div>
    </template>


    <script>
        class TpDrag extends HTMLElement {
            constructor() {
                super();

                let template = document.getElementById('tp-drag');

                let shadow = this.attachShadow({ mode: 'closed' });

                let tp_content = template.content.cloneNode(true);

                this.$title = tp_content.getElementById('title');

                this.$title.textContent = this.getAttribute('title');
                
                this.$content = tp_content.getElementById('content');

                this.$content.setAttribute('cid',this.id);

                shadow.appendChild(tp_content);
            }

        }

        customElements.define('tp-drag', TpDrag);

    </script>
</body>

</html>